﻿// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone

using Bootstrap.Security.Blazor;
using BootstrapClient.DataAccess.Models;
using BootstrapClient.Web.Core;
using BootstrapClient.Web.Shared.Services;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.JSInterop;
using SqlSugar;

namespace BootstrapClient.Web.Shared.Components
{
    /// <summary>
    /// 
    /// </summary>
    [JSModuleAutoLoader]
    public partial class AdminTable<TItem> where TItem : class, new()
    {
        private string? clientTableName = null;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public IEnumerable<int>? PageItemsSource { get; set; } = new List<int>() { 10, 20, 50, 100, 1000 };

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public int ExtendButtonColumnWidth { get; set; } = 130;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public string? SortString { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [NotNull]
        [Parameter]
        public RenderFragment<TItem>? TableColumns { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public RenderFragment<TItem>? RowButtonTemplate { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public RenderFragment<ITableSearchModel>? CustomerSearchTemplate { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public RenderFragment<TItem>? EditTemplate { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [NotNull]
        [Parameter]
        public RenderFragment? TableToolbarTemplate { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool IsPagination { get; set; } = true;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool IsMultipleSelect { get; set; } = true;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool IsFixedHeader { get; set; } = true;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool IsTree { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool ShowToolbar { get; set; } = true;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool ShowEmpty { get; set; } = true;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool ShowLoading { get; set; } = false;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool ShowSearch { get; set; } = true;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool ShowAdvancedSearch { get; set; } = true;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool ShowDefaultButtons { get; set; } = true;

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public bool ShowExtendButtons { get; set; } = true;

        /// <summary>
        ///  获得/设置 是否显示导出按钮
        /// </summary>
        [Parameter]
        public bool ShowExportButton { get; set; } = true;

        /// <summary>
        /// 获得/设置 是否显示 Csv 导出按钮
        /// </summary>
        [Parameter]
        public bool ShowExportCsvButton { get; set; } = true;

        /// <summary>
        /// 获得/设置 是否自动生成列信息
        /// </summary>
        [Parameter]
        public bool AutoGenerateColumns { get; set; } = true;

        [Inject]
        AuthenticationStateProvider AuthenticationStateProvider { get; set; }
        /// <summary>
        /// 获得/设置 客户端表格名称 默认 null 用于客户端列宽与列顺序持久化功能
        /// </summary>
        [Parameter]
        public string? ClientTableName
        {
            get => clientTableName;
            set
            {
                var user = AuthenticationStateProvider.GetAuthenticationStateAsync().Result.User.Identity?.Name ?? "not-user";
                clientTableName = $"{value}-{user}";
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public ITableSearchModel? CustomerSearchModel { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public Func<QueryPageOptions, Task<QueryData<TItem>>>? OnQueryAsync { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public Func<TItem, Task<IEnumerable<TableTreeNode<TItem>>>>? OnTreeExpand { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public Func<IEnumerable<TItem>, Task<IEnumerable<TableTreeNode<TItem>>>>? TreeNodeConverter { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public Func<TItem, ItemChangedType, Task<bool>>? OnSaveAsync { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public Func<IEnumerable<TItem>, Task<bool>>? OnDeleteAsync { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Parameter]
        public List<TItem>? SelectedRows { get; set; } = new List<TItem>();

        /// <summary>
        /// 获得/设置 是否显示行内扩展编辑按钮 默认为 null 未设置时使用
        /// </summary>
        [Parameter]
        public Func<TItem, bool>? ShowExtendEditButtonCallback { get; set; }

        /// <summary>
        /// 获得/设置 是否显示行内扩展删除按钮 默认为 null 未设置时使用
        /// </summary>
        [Parameter]
        public Func<TItem, bool>? ShowExtendDeleteButtonCallback { get; set; }


        [NotNull]
        private Table<TItem>? Instance { get; set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="v"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public ValueTask ToggleLoading(bool v) => Instance.ToggleLoading(v);

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public Task QueryAsync() => Instance.QueryAsync();


        private IEnumerable<ITableColumn> OnColumnOrderCallback(IEnumerable<ITableColumn> columns)
        {
            return columns;
        }



        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            await base.OnAfterRenderAsync(firstRender);
            await SetTableInfoAsync();
        }

        private async Task OnDragColumnEndAsync(string columnName, IEnumerable<ITableColumn> columns)
        {
            await UpdateTableInfoAsync();
        }

        private async Task OnResizeColumnAsync(string columnName, float width)
        {
            await UpdateTableInfoAsync();
        }



        [Inject]
        private IJSRuntime? JSRuntime { get; set; }

        [Inject]
        private SqlSugar.ISqlSugarClient db { get; set; }
        private async Task SetTableInfoAsync()
        {
            var ctName = ClientTableName;

            var orders = await JSRuntime.InvokeAsync<string>("reloadColumnOrderEx", ctName);
            var colwid = await JSRuntime.InvokeAsync<string>("reloadColumnWidthEx", ctName);
            if (orders is null || string.IsNullOrEmpty(colwid))
            {
                var a = db.Queryable<UserLocalStorageData>().Where(t => t.Name == $"bb-table-column-order-{ctName}").Single();
                var b = db.Queryable<UserLocalStorageData>().Where(t => t.Name == $"bb-table-column-width-{ctName}").Single();

                //保存服务器数据
                if (a != null)
                {
                    await JSRuntime.InvokeVoidAsync("saveColumnOrderEx", new { tableName = ctName, data = a.Value });
                }
                if (b != null)
                {
                    await JSRuntime.InvokeVoidAsync("saveColumnWidthEx", new { tableName = ctName, data = b.Value });
                }
            }
        }

        private async Task UpdateTableInfoAsync()
        {
            var ctName = ClientTableName;
            var order = await JSRuntime.InvokeAsync<string?>("reloadColumnOrderEx", ClientTableName);
            var colwid = await JSRuntime.InvokeAsync<string>("reloadColumnWidthEx", ClientTableName);

            if (order != null)
            {
                db.Storageable(new UserLocalStorageData()
                {
                    Id = SnowFlakeSingle.Instance.NextId().ToString(),
                    Name = $"bb-table-column-order-{ctName}",
                    Value = order
                }).WhereColumns(t => t.Name).ExecuteCommand();
            }
            if (colwid != null)
            {
                db.Storageable(new UserLocalStorageData()
                {
                    Id = SnowFlakeSingle.Instance.NextId().ToString(),
                    Name = $"bb-table-column-width-{ctName}",
                    Value = colwid
                }).WhereColumns(t => t.Name).ExecuteCommand();
            }
        }

        [Inject]
        [NotNull]
        private IBootstrapAdminService? AdminService { get; set; }

        [Inject]
        [NotNull]
        private NavigationManager? NavigationManager { get; set; }

        [Inject]
        [NotNull]
        private BootstrapAppContext? AppContext { get; set; }

        private bool AuthorizeButton(string operate)
        {
            var url = NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
            return AdminService.AuthorizingBlock(AppContext.UserName, url, operate);
        }
    }
}
